package com.laikan.library.utils;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ThumbnailUtils;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import com.socks.library.KLog;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

public class AndroidUtils {

    /**
     * @param original
     * @param color
     * @param targets
     *
     * @return
     */
    public static SpannableString getHighLightString(String original, int color, String... targets) {

        SpannableString sp = new SpannableString(original);
        try {
            for (String target : targets) {
                int start = original.indexOf(target);
                int end = start + target.length();
                sp.setSpan(new ForegroundColorSpan(color), start, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return sp;
    }

    private static final String TAG = AndroidUtils.class.getSimpleName();

    public static Bitmap extractThumbNail(final String imagePath, final int height, final int width, final boolean crop) {

        try {
            Bitmap bitmap = null;
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            // 获取这个图片的宽和高，注意此处的bitmap为null
            bitmap = BitmapFactory.decodeFile(imagePath, options);
            options.inJustDecodeBounds = false; // 设为 false
            // 计算缩放比
            int h = options.outHeight;
            int w = options.outWidth;
            int beWidth = w / width;
            int beHeight = h / height;
            int be = 1;
            if (beWidth < beHeight) {
                be = beWidth;
            }else {
                be = beHeight;
            }
            if (be <= 0) {
                be = 1;
            }
            options.inSampleSize = be;
            // 重新读入图片，读取缩放后的bitmap，注意这次要把options.inJustDecodeBounds 设为 false
            bitmap = BitmapFactory.decodeFile(imagePath, options);
            // 利用ThumbnailUtils来创建缩略图，这里要指定要缩放哪个Bitmap对象
            bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
            if (crop) {
                Bitmap cropped = Bitmap.createBitmap(bitmap, (bitmap.getWidth() - width) >> 1, (bitmap.getHeight() - height) >> 1, width, height);
                if (cropped == null) {
                    return bitmap;
                }
                bitmap.recycle();
                bitmap = null;
                return cropped;
            }else {
                return bitmap;
            }
        }catch (final Exception e) {
            KLog.e("decode bitmap failed: " + e.getMessage());
        }catch (final OutOfMemoryError e) {
            KLog.e("decode bitmap failed: " + e.getMessage());
        }
        return null;
    }

    public static Bitmap compressImage(String imagePath) {

        try {
            Bitmap bitmap = null;
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            // 获取这个图片的宽和高，注意此处的bitmap为null
            bitmap = BitmapFactory.decodeFile(imagePath, options);
            options.inJustDecodeBounds = false; // 设为 false
            // 计算缩放比
            int h = options.outHeight;
            int w = options.outWidth;
            int height = 800;// 这里设置高度为800
            int width = 480;// 这里设置宽度为480
            int beWidth = w / width;
            int beHeight = h / height;
            int be = 1;
            if (beWidth < beHeight) {
                be = beWidth;
            }else {
                be = beHeight;
            }
            if (be <= 0) {
                be = 1;
            }
            options.inSampleSize = be;
            // 重新读入图片，读取缩放后的bitmap，注意这次要把options.inJustDecodeBounds 设为 false
            bitmap = BitmapFactory.decodeFile(imagePath, options);
            // 压缩
            int quality = 100;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
            while (baos.toByteArray().length > 90 * 1024 && quality > 50) { // 循环判断如果压缩后图片是否大于maxSize,大于继续压缩
                baos.reset();// 重置baos即清空baos
                quality -= 10;// 每次都减少10
                bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);// 这里压缩quality%，把压缩后的数据存放到baos中
            }
            Bitmap result = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length);
            bitmap.recycle();
            bitmap = null;
            return result;
        }catch (OutOfMemoryError e) {
            return BitmapFactory.decodeFile(imagePath);
        }finally {
            System.gc();
        }
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {

        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(Context context, float pxValue) {

        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(pxValue / scale + 0.5f);
    }

    public static boolean isChineseHanZi(String str) {

        for (int i = 0; i < str.length(); i++) {
            char ss = str.charAt(i);
            boolean hanzi = String.valueOf(ss).matches("[\u4e00-\u9fa5]");
            if (!hanzi) {
                return false;
            }
        }
        return true;
    }

    public static String getMD5(String content) {

        if (TextUtils.isEmpty(content)) {
            return null;
        }
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            md5.update(content.getBytes());
            byte[] m = md5.digest();
            return binaryToHexString(m);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }

    private static String binaryToHexString(byte[] messageDigest) {

        if (messageDigest == null) {
            return null;
        }
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < messageDigest.length; i++) {
            int by = 0xFF & messageDigest[i];
            if (by < 0x10) {
                hexString.append("0" + Integer.toHexString(by));
            }else if (by >= 0x10) {
                hexString.append(Integer.toHexString(by));
            }
        }
        return hexString.toString();
    }

    public static Bitmap scaleBitmap(Bitmap bitmap, int width, int height) {

        // 获得图片的宽高
        int originWidth = bitmap.getWidth();
        int originHeight = bitmap.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float)width) / originWidth;
        float scaleHeight = ((float)height) / originHeight;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 得到新的图片
        Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        bitmap.recycle();
        bitmap = null;
        return resizeBitmap;
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

        // 源图片的高度和宽度
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            // 计算出实际宽高和目标宽高的比率
            final int heightRatio = Math.round((float)height / (float)reqHeight);
            final int widthRatio = Math.round((float)width / (float)reqWidth);
            // 选择宽和高中最小的比率作为inSampleSize的值，这样可以保证最终图片的宽和高 // 一定都会大于等于目标的宽和高。
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        KLog.d("=========inSampleSize = " + inSampleSize);
        return inSampleSize;
    }

    public static Bitmap decodeSampleBitmap(String imagePath, int sdwidth, int sdheight) {

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, options);
        options.inSampleSize = calculateInSampleSize(options, sdwidth, sdheight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        return BitmapFactory.decodeFile(imagePath, options);
    }

    // 递归删除文件及文件夹
    public static void deleteFile(File file, boolean fileOnly) {

        if (file.isFile()) {
            file.delete();
            return;
        }
        if (file.isDirectory()) {
            File[] childFiles = file.listFiles();
            if (childFiles == null || childFiles.length == 0) {
                if (!fileOnly) {
                    file.delete();
                }
                return;
            }
            for (int i = 0; i < childFiles.length; i++) {
                deleteFile(childFiles[i], fileOnly);
            }
            if (!fileOnly) {
                file.delete();
            }
        }
    }

    public static Bitmap createImageThumbnail(String filePath, int width, int height) {

        Bitmap bitmap = null;
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, width, height);
        opts.inJustDecodeBounds = false;
        try {
            bitmap = BitmapFactory.decodeFile(filePath, opts);
        }catch (Exception e) {
            // TODO: handle exception
        }
        return bitmap;
    }

    public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int width, int height) {

        int initialSize = computeInitialSampleSize(options, minSideLength, width, height);
        int roundedSize;
        if (initialSize <= 8) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        }else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }
        return roundedSize;
    }

    private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int width, int height) {

        double w = options.outWidth;
        double h = options.outHeight;
        int maxNumOfPixels = width * height;
        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int)Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? Math.min(width, height) : (int)Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
        if (upperBound < lowerBound) {
            // return the larger one when there is no overlapping zone.
            return lowerBound;
        }
        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
            return 1;
        }else if (minSideLength == -1) {
            return lowerBound;
        }else {
            return upperBound;
        }
    }

    public static int getScreenWidth(Activity context) {

        WindowManager wm = context.getWindowManager();
        return wm.getDefaultDisplay().getWidth();
    }

    public static int getScreenHeight(Activity context) {

        WindowManager wm = context.getWindowManager();
        return wm.getDefaultDisplay().getHeight();
    }

    public static String getCurrentAppVer(Context context) {

        try {
            PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return pi.versionName;
        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "未知";
        }
    }

    public static String encodeParameters(Map<String, String> params, String paramsEncoding) {

        StringBuilder encodedParams = new StringBuilder();
        if (params != null) {

            try {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    String key = entry.getKey() == null ? "" : entry.getKey();
                    String value = entry.getValue() == null ? "" : entry.getValue();
                    encodedParams.append(URLEncoder.encode(key, paramsEncoding));
                    encodedParams.append('=');
                    encodedParams.append(URLEncoder.encode(value, paramsEncoding));
                    encodedParams.append('&');
                }
                if (encodedParams.length() != 0) {
                    encodedParams.deleteCharAt(encodedParams.length() - 1);
                }
                KLog.i("encode success");
                return encodedParams.toString();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * 动态获取状态栏高度
     */
    public static int getTitleBarHeight(Context context) {
        Class<?> c;
        Object obj;
        Field field;
        int sbar = 0;
        int x;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            obj = c.newInstance();
            field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            sbar = context.getResources().getDimensionPixelSize(x);
        }catch (Exception e1) {
            e1.printStackTrace();
        }
        return sbar;
    }

    /**
     * 获取 虚拟按键的高度
     *
     * @param context
     *
     * @return
     */
    public static int getVirtualKeyHeight(Context context) {
        int totalHeight = getDpi(context);
        int contentHeight = getScreenHeight(context);
        return totalHeight - contentHeight;
    }

    /**
     * 获取屏幕的高度
     *
     * @param context
     *
     * @return
     */
    public static int getScreenHeight(Context context) {
        WindowManager wm = (WindowManager)context
            .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.heightPixels;
    }

    /**
     * 获取虚拟按键高度
     *
     * @param context
     *
     * @return
     */
    public static int getDpi(Context context) {
        int dpi = 0;
        WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        @SuppressWarnings ("rawtypes")
        Class c;
        try {
            c = Class.forName("android.view.Display");
            @SuppressWarnings ("unchecked")
            Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, displayMetrics);
            dpi = displayMetrics.heightPixels;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return dpi;
    }

}
